#pragma once

#include <iostream>
#include <vector>
#include <unordered_map>
#include <fstream>
#include "Common.hpp"
#include "Log.hpp"
const std::string Sep = "\r\n";
const std::string LineSep = " ";
const std::string BlankLine = Sep;
const std::string HeaderLineSep = ":";
const std::string defaulthome = "wwwroot";
const std::string http_verson = "HTTP/1.0";
const std::string page404 = "wwwroot/404.html";
const std::string firstpage = "index.html";
using namespace LogModule;
class HttpRequest
{

public:
    HttpRequest() {}
    ~HttpRequest() {}
    bool IsHashArgs()
    {
        return _isexec;
    }
    bool SplitString(std::string header, std::string HeaderLineSep, std::string *key, std::string *val)
    {
        auto pos = header.find(HeaderLineSep);
        if (pos == std::string::npos)
            return false;
        *key = header.substr(0, pos);
        *val = header.substr(pos + HeaderLineSep.size());
        return true;
    }
    void ParseHeaderKv()
    {
        for (auto header : req_headers)
        {
            std::string key, value;
            SplitString(header, HeaderLineSep, &key, &value);
            _header_kv[key] = value;
        }
    }
    bool ParseHeader(std::string& req_str)
    {
        LOG(LogLevel::DEBUG)<<" 删除了请求行后还剩下这些"<<req_str;
        std::string line;
        while (true)
        {
            bool is = ParseOneLine(req_str, &line, Sep);
            if (!is)
            {
                return false;
            }
            if (line.empty())
            {
                _balnk_line = Sep;
                break; // 读到了空行
            }
            req_headers.push_back(line);
        }
        return true;
    }
    std::string Path()
    {
        return _path;
    }
    std::string Args()
    {
        return _args;
    }
    void Deserialize(std::string req_str)
    {
        // 拿到第一行---请求行
        if (ParseOneLine(req_str, &_req_line, Sep))
        // 对第一行继续分割
        {
            ParseReqLine(_req_line, LineSep);
            ParseHeader(req_str);
            LOG(LogLevel::DEBUG)<<"现在主体是:"<<req_str;
            _body = req_str;
            ParseHeaderKv();
            if (_method == "POST")
            {
                _isexec = true; // 参数在正文
                _args = _body;
                _path = _url;
                LOG(LogLevel::DEBUG)<<"POST _path:"<<_path;
                LOG(LogLevel::DEBUG)<<"POST _args:"<<_args;
            }
            else if (_method == "GET")
            {
                auto pos = _url.find("?");
                if (pos != std::string::npos)
                {
                    _isexec = true;              // 参数在uri
                    _path = _url.substr(0, pos); //_route的k值
                    _args = _url.substr(pos + 1);
                    LOG(LogLevel::DEBUG)<<"_path"<<_path<<"_args"<<_args;
                }
            }
        }
    }
    void Print()
    {
        std::cout << "_method:" << _method << std::endl;
        std::cout << "_url:" << _url << std::endl;
        std::cout << "_version:" << _version << std::endl;
        for (auto kv : _header_kv)
        {
            std::cout << kv.first << ":" << kv.second << std::endl;
        }
        std::cout << "正文" << _body << std::endl;
    }
    std::string URL()
    {
        return _url;
    }
    void SetUrl(const std::string url)
    {
        _url = url;
    }
    std::string GetContent(std::string url)
    {
        // std::string content;
        // std::ifstream in(_url);
        // if (in.is_open() == 0)
        //     return "";
        // std::string line;
        // while (std::getline(in, line))
        //     content += line;

        // in.close();
        // return content;
        LOG(LogLevel::DEBUG)<<"GetContent start";
        std::string content;
        std::ifstream in(url, std::ios::binary);
        if (in.is_open() == 0)
        {
            LOG(LogLevel::ERROR)<<"GetContent failed";
            return "";
        }
           
        in.seekg(0, in.end);
        int filesize = in.tellg();
        in.seekg(0, in.beg);
        content.resize(filesize);
        in.read((char *)content.c_str(), filesize);
        in.close();
        LOG(LogLevel::DEBUG)<<"GetContent success";
        return content;
    }
    std::string Suffix()
    {
        std::string suffix;
        auto pos = _url.rfind(".");
        if (pos == std::string::npos)
            return ".html";
        suffix = _url.substr(pos);
        return suffix;
    }

private:
    void ParseReqLine(std::string req_line, std::string LineSep)
    {
        // 分割请求行
        std::stringstream ss(req_line);
        ss >> _method >> _url >> _version;
    }
    std::string _req_line;
    std::string _balnk_line;
    std::vector<std::string> req_headers;
    std::string _body;
    std::string _method;
    std::string _url;
    std::string _version;
    std::unordered_map<std::string, std::string> _header_kv;
    bool _isexec = false;
    std::string _path;
    std::string _args;
};
// 对于http，任何请求都要有应答，就算没有正文也要应答
class HttpResponse
{
public:
    HttpResponse()
        : _verson(http_verson), _blank_line(BlankLine)
    {
    }
    ~HttpResponse() {}
    void BuildResponse(HttpRequest &req)
    {
        // #define TestRedir 1
        // #ifdef TestRedir

        // if (uri == "wwwroot/aaa")
        //     {
        //         _status_code = "301";
        //         _status_desc = CodeToDesc(_status_code);
        //         SetHeader("Location", "https://47.98.230.86:8082/register.html");
        //         for (auto header : _header_kv)
        //         {
        //             _res_headers.push_back(header.first + HeaderLineSep + header.second);
        //         }
        //         return ;
        //     }

        // #else
        std::string url =  req.URL();
        if (url.back() == '/')
       {
         url=url+=firstpage;   
        req.SetUrl(url);
    }
  
    url=defaulthome+url;
            _body = req.GetContent(url);
            LOG(LogLevel::DEBUG)<<"看一下请求内容";
        req.Print();
        LOG(LogLevel::DEBUG)<<"看一下请求内容";

        if (_body.empty()) // 则用户请求资源不存在
        {
            _status_code = "404";
            req.SetUrl(page404);
            _body = req.GetContent(page404);
        }
        else
        {
            _status_code = "200";
        }
        _status_desc = CodeToDesc(_status_code);
        if (!_body.empty())
        {
            SetHeader("Content-Length", std::to_string(_body.size()));
        }
        std::string mime_type = SuffixToDesc(req.Suffix());
        SetHeader("Content-Type", mime_type);
        LOG(LogLevel::DEBUG) << "客户端请求" << req.URL() << "成功";

        // for (auto header : _header_kv)
        // {
        //     _res_headers.push_back(header.first + HeaderLineSep + header.second);
        // }
        LOG(LogLevel::DEBUG) << "BuildResponse success";
        // #endif
    }
    void SetCode(int code)
    {
        _status_code=std::to_string(code);
        _status_desc=CodeToDesc(_status_code);
    }
void SetBody(std::string body)
{
    _body = body;
}
    std::string CodeToDesc(std::string code)
    {
        if (code == "200")
            return "OK";
        else if (code == "404")
            return "Not Found";
        else if (code == "302")
            return "Found";
        else if (code == "301")
            return "Moved Permanently";
        else
            return "Unknown";
    }
    void Serialize(std::string *res_str)
    {
        *res_str = _verson + LineSep + _status_code + LineSep + _status_desc + Sep;
        for (auto header : _res_headers)
        {
            *res_str += header + Sep;
        }
        *res_str += _blank_line;
        *res_str += _body;
        LOG(LogLevel::DEBUG) << "Serialize success";
    }

    void SetHeader(std::string key, std::string value)
    {
        _header_kv[key] = value;
        _res_headers.push_back(key + HeaderLineSep + value);
    }
    void Deserialize(std::string res_str)
    {
    }
    std::string SuffixToDesc(std::string suffix)
    {
        if (suffix == ".html")
            return "text/html";
        else if (suffix == ".jpg")
            return "image/jepg";
        else
            return "text/html";
    }

private:
    std::string _verson;
    std::string _status_code;
    std::string _status_desc;
    std::string _res_line;
    std::string _blank_line;
    std::vector<std::string> _res_headers;
    std::string _body;
    std::unordered_map<std::string, std::string> _header_kv;
};
